import { AppDataSource } from '../../data-source'
import { Request, Response } from 'express'
import { Random } from '../../utils/random-utils'
import { responseHandler, errorHandler, paramsHandler } from '../../utils/handler-utils'
import { deleteFile, videoProjectDir, moveFile, staticDir } from "../../utils/storage-utils";
import { NodeEntity } from '../../entity/node_entity'
import { VideoEntity } from '../../entity/video_entity'
import { pathToURL, urlToPath } from "../../utils/address-utils";
import { generateVideoThumbnail } from "../../utils/ffmpeg-utils";
import { videoProjectEntity } from '../../entity/videoProject_entity';
import * as path from "path"
import * as fs from 'fs';

import type { UploadedFile } from "../../middleware/upload.middleware";
import type {
    UploadNodeVideoRequestBody,
    DeleteNodeVideoRequestBody
} from "./types";

const random = new Random()
const projectRepository = AppDataSource.getRepository(videoProjectEntity)
const nodeRepository = AppDataSource.getRepository(NodeEntity)
const videoRepository = AppDataSource.getRepository(VideoEntity)

class Actions {

    /**
  * 上传节点信息
  * @returns 
  */
    uploadNodeList = async (req: Request, res: Response) => {
        // console.log(req.body)
        try {
            const { projectId, nodes } = req.body;

            if (projectId == undefined || nodes == undefined) {
                // 参数错误
                paramsHandler(req.body, req, res)
                return
            }

            let projectEntity = await projectRepository.findOne({ where: { id: projectId as String } });
            if (projectEntity == null) {
                responseHandler({
                    req,
                    res,
                    code: 1,
                    data: {
                        "error": "当前项目不存在或者已经被删除 id : " + projectId
                    },
                    message: "获取失败",
                })
                return
            }
            // 删除 节点列表
            let oldNodeList: NodeEntity[] = await nodeRepository.find({ where: { projectId: projectEntity.id } });
            let newNodeList: UploadNodeVideoRequestBody[] = nodes as UploadNodeVideoRequestBody[];

            for (let index = 0; index < newNodeList.length; index++) {
                const element = newNodeList[index];
                let oldRemoveIndex = oldNodeList.findIndex(node => node.id === element.id);
                if (oldRemoveIndex !== -1) {
                    let nodeInfoEntity = oldNodeList[oldRemoveIndex];
                    nodeInfoEntity.type = element.type;
                    nodeInfoEntity.title = element.title;
                    nodeInfoEntity.widgetOffset = element.widgetOffset;
                    nodeInfoEntity.inputData = element.inputData;
                    nodeInfoEntity.outputData = element.outputData;
                    nodeInfoEntity.thumbnail = element.thumbnail;
                    nodeInfoEntity.videoUrl = element.videoUrl;
                    nodeInfoEntity.question = element.question;
                    nodeInfoEntity.styleLayout = element.styleLayout;
                    await nodeRepository.save(nodeInfoEntity);

                    // 使用 filter 方法来删除指定元素
                    oldNodeList = oldNodeList.filter(item => item.id != element.id);
                } else {
                    let nodeInfoEntity = new NodeEntity()
                    nodeInfoEntity.id = element.id;
                    nodeInfoEntity.projectId = element.projectId;
                    nodeInfoEntity.type = element.type;
                    nodeInfoEntity.title = element.title;
                    nodeInfoEntity.widgetOffset = element.widgetOffset;
                    nodeInfoEntity.inputData = element.inputData;
                    nodeInfoEntity.outputData = element.outputData;
                    nodeInfoEntity.thumbnail = element.thumbnail;
                    nodeInfoEntity.videoUrl = element.videoUrl;
                    nodeInfoEntity.question = element.question;
                    nodeInfoEntity.styleLayout = element.styleLayout;
                    await nodeRepository.save(nodeInfoEntity);
                }
            }

            for (let index = 0; index < oldNodeList.length; index++) {
                const element = oldNodeList[index];
                await nodeRepository.remove(element);
            }

            responseHandler({
                req,
                res,
                code: 0,
                data: { "msg": "ok" },
                message: "节点上传成功",
            })

        } catch (error) {
            errorHandler({
                error,
                message: "上传失败",
                data: { error },
                req,
                res,
            })
        }
    };

    /**
     * 上传节点信息
     * @returns 
     */
    uploadNodeInfo = async (req: Request, res: Response) => {
        try {

            // 首先声明一个注册 消息的结构体
            var uploadBody = req.body as UploadNodeVideoRequestBody;
            if (uploadBody.id == undefined ||
                uploadBody.projectId == undefined ||
                uploadBody.type == undefined ||
                uploadBody.title == undefined ||
                uploadBody.widgetOffset == undefined ||
                uploadBody.inputData == undefined ||
                uploadBody.outputData == undefined ||
                uploadBody.thumbnail == undefined ||
                uploadBody.videoUrl == undefined ||
                uploadBody.question == undefined ||
                uploadBody.styleLayout == undefined) {
                // 参数错误
                paramsHandler(req.body, req, res)
                return
            }
            let mindItemEntity = new NodeEntity()

            mindItemEntity.id = uploadBody.id;
            mindItemEntity.projectId = uploadBody.projectId;
            mindItemEntity.type = uploadBody.type;
            mindItemEntity.title = uploadBody.title;
            mindItemEntity.widgetOffset = uploadBody.widgetOffset;
            mindItemEntity.inputData = uploadBody.inputData;
            mindItemEntity.outputData = uploadBody.outputData;
            mindItemEntity.thumbnail = uploadBody.thumbnail;
            mindItemEntity.videoUrl = uploadBody.videoUrl;
            mindItemEntity.question = uploadBody.question;
            mindItemEntity.styleLayout = uploadBody.styleLayout;
            nodeRepository.save(mindItemEntity);

            responseHandler({
                req,
                res,
                code: 0,
                data: mindItemEntity,
                message: "节点上传成功",
            })

        } catch (error) {
            errorHandler({
                req,
                error,
                message: "上传失败",
                data: { error },
                res,
            })
        }
    };
    /**
    * 清除所有节点
    * @returns 
    */
    clearNodeList = async (req: Request, res: Response) => {
        // console.log(req.body)
        try {
            const { projectId } = req.body;

            if (projectId == undefined) {
                // 参数错误
                paramsHandler(req.body, req, res)
                return
            }

            let projectEntity = await projectRepository.findOne({ where: { id: projectId as String } });
            if (projectEntity == null) {
                responseHandler({
                    req,
                    res,
                    code: 1,
                    data: {
                        "error": "当前项目不存在或者已经被删除 id : " + projectId
                    },
                    message: "获取失败",
                })
                return
            }
            // 删除 节点列表
            let oldNodeList: NodeEntity[] = await nodeRepository.find({ where: { projectId: projectEntity.id } });

            for (let index = 0; index < oldNodeList.length; index++) {
                const element = oldNodeList[index];
                await nodeRepository.remove(element);
            }

            responseHandler({
                req,
                res,
                code: 0,
                data: { "msg": "ok" },
                message: "节点清除成功",
            })

        } catch (error) {
            errorHandler({
                req,
                error,
                message: "节点清除失败",
                data: { error },
                res,
            })
        }
    };

    /**
     * 删除视频
     * @returns 
     */
    deleteNodeInfo = async (req: Request, res: Response) => {

        try {

            // 首先声明一个注册 消息的结构体
            var deleteBody = req.body as DeleteNodeVideoRequestBody;
            if (deleteBody.projectId == undefined || deleteBody.nodeId == undefined) {
                // 参数错误
                paramsHandler(req.body, req, res)
                return
            }

            let mindItemEntity = await nodeRepository.findOneBy({ id: deleteBody.nodeId, projectId: deleteBody.projectId });
            if (mindItemEntity) {
                let videoPath = urlToPath(mindItemEntity.videoUrl.toString());
                await deleteFile(videoPath);
                let thumbnailPath = urlToPath(mindItemEntity.thumbnail.toString());
                await deleteFile(thumbnailPath);
                nodeRepository.remove(mindItemEntity);
                responseHandler({
                    req,
                    res,
                    code: 0,
                    data: null,
                    message: "删除成功",
                })
            } else {
                responseHandler({
                    req,
                    res,
                    code: 0,
                    data: {
                        msg: "数据不存在,或者已经删除"
                    },
                    message: "删除成功",
                })
            }

        } catch (error) {
            errorHandler({
                error,
                message: "删除失败",
                data: { error },
                req,
                res,
            })
        }
    };

    /**
    * 节点信息列表
    * @returns 
    */
    nodeInfoList = async (req: Request, res: Response) => {
        try {
            const { projectId } = req.query;

            if (projectId == undefined) {
                // 参数错误
                paramsHandler(req.body, req, res)
                return
            }
            let nodeList: NodeEntity[] = await nodeRepository.find({
                where: { projectId: projectId as String }
            });

            responseHandler({
                req,
                res,
                code: 0,
                data: nodeList,
                message: "获取成功",
            })

        } catch (error) {
            errorHandler({
                error,
                message: "获取失败",
                data: { error },
                req,
                res,
            })
        }
    };

    /**
    * 上传节点信息
    * @returns 
    */
    uploadVideo = async (req: Request, res: Response) => {

        if (req.files.length == 0) {
            responseHandler({
                httpStatus: 400,
                code: 1,
                message: "未检测到上传文件",
                res,
                req,
            });
            return;
        }

        const { projectId } = req.body;
        if (projectId == undefined || projectId == "") {
            // 参数错误
            paramsHandler(req.body, req, res)
            return
        }

        try {

            // 查询数据库实体
            let projectEntity = await projectRepository.findOneBy({ id: projectId });
            if (projectEntity == null) {
                responseHandler({
                    req,
                    res,
                    code: 1,
                    data: {
                        msg: `当前工程不存在  工程Id:${projectId}`
                    },
                    message: "上传失败",
                })
            } else {

                // 这里的 req.files 是一个 UploadedFile 类型的数组
                let uploadedFiles: UploadedFile[] = req.files as UploadedFile[];
                let videoEntitys: VideoEntity[] = [];

                for (let index = 0; index < uploadedFiles.length; index++) {
                    const file = uploadedFiles[index];
                    // console.log(file.originalname);
                    // console.log(file.encoding);
                    // console.log(file.mimetype);
                    // console.log(file.size);
                    // console.log(file.destination);
                    // console.log(file.filename);
                    // console.log(file.path);
                    // 移动文件到指定目录
                    var targetPath = path.join(videoProjectDir, projectId, file.filename);
                    await moveFile(file.path, targetPath);
                    var videoThumbnailPath = await generateVideoThumbnail(targetPath, ".jpg");

                    let videoEntity = new VideoEntity()

                    videoEntity.id = random.randomString();
                    videoEntity.projectId = projectId;
                    videoEntity.fileName = file.filename;
                    videoEntity.thumbnail = pathToURL(videoThumbnailPath);
                    videoEntity.videoUrl = pathToURL(targetPath);
                    videoRepository.save(videoEntity);
                    videoEntitys.push(videoEntity);
                }

                responseHandler({
                    req,
                    res,
                    code: 0,
                    data: {
                        "projectId": projectId,
                        "operation": "upload files",
                        "files": videoEntitys,
                        "status": "ok"
                    },
                    message: "上传文件成功",
                })
            }

        } catch (error) {
            errorHandler({
                error,
                message: "上传失败",
                data: { error },
                req,
                res,
            })
        }
    };

    /**
     * 删除视频
     * @returns 
     */
    deleteVideo = async (req: Request, res: Response) => {
        const { projectId, videoIds } = req.body;

        try {

            if (projectId == undefined || videoIds == undefined) {
                // 参数错误
                paramsHandler(req.body, req, res)
                return
            }

            if (Array.isArray(videoIds)) {
                let deleteIds: string[] = videoIds as string[];
                for (let index = 0; index < deleteIds.length; index++) {
                    const id = deleteIds[index];
                    let videoEntity = await videoRepository.findOneBy({ id: id, projectId: projectId });
                    if (videoEntity) {
                        let videoPath = urlToPath(videoEntity.videoUrl.toString());
                        await deleteFile(videoPath);
                        let thumbnailPath = urlToPath(videoEntity.thumbnail.toString());
                        await deleteFile(thumbnailPath);
                        videoRepository.remove(videoEntity);
                    }
                }
            } else {
                const id = videoIds as string;
                let videoEntity = await videoRepository.findOneBy({ id: id, projectId: projectId });
                if (videoEntity) {
                    let videoPath = urlToPath(videoEntity.videoUrl.toString());
                    await deleteFile(videoPath);
                    let thumbnailPath = urlToPath(videoEntity.thumbnail.toString());
                    await deleteFile(thumbnailPath);
                    videoRepository.remove(videoEntity);
                }
            }

            responseHandler({
                req,
                res,
                code: 0,
                data: null,
                message: "删除成功",
            })

        } catch (error) {
            errorHandler({
                error,
                message: "删除失败",
                data: { error },
                req,
                res,
            })
        }
    };

    /**
     * 视频列表
     * @returns 
     */
    videoList = async (req: Request, res: Response) => {
        const { projectId } = req.query;
        try {

            if (projectId == undefined) {
                // 参数错误
                paramsHandler(req.body, req, res)
                return
            }

            let videoProjectId: String = projectId as String;

            let videoEntityList = await videoRepository.find({ where: { projectId: videoProjectId } });
            responseHandler({
                req,
                res,
                code: 0,
                data: videoEntityList,
                message: "获取成功",
            })

        } catch (error) {
            errorHandler({
                error,
                message: "获取失败",
                data: { error },
                req,
                res,
            })
        }
    };
    /**
     * 视频下载
     * @returns 
     */
    downloadVideo = async (req: Request, res: Response) => {
        // console.log('下载------');
        const filePath = path.join(staticDir, req.query.path as string); // 从GET请求中获取文件路径参数
        const videoName = path.basename(filePath); // 获取视频文件名

        // 检查文件路径是否有效
        if (!filePath || !fs.existsSync(filePath)) {
            res.status(404).send('Video not found');
            return;
        }

        // 设置响应头，指示这是一个文件下载请求
        res.download(filePath, videoName, (err) => {
            if (err) {
                // 处理错误，例如文件不存在或无法读取
                res.status(500).send('Error downloading video');
            }
        });
    };
}

export const action = new Actions();